package com.flex.mobile.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javapns.Push;
import javapns.communication.exceptions.CommunicationException;
import javapns.communication.exceptions.KeystoreException;
import javapns.notification.PushedNotification;
import javapns.notification.ResponsePacket;

import com.flex.mobile.constant.OrderInfoStatusConst;
import com.flex.mobile.constant.OrderInfoTypeConst;
import com.flex.mobile.dao.impl.CustInfoDao;
import com.flex.mobile.dao.impl.DriverInfoDao;
import com.flex.mobile.dao.impl.DriverOrderDao;
import com.flex.mobile.dao.impl.OrderInfoDao;
import com.flex.mobile.dao.model.CustInfo;
import com.flex.mobile.dao.model.DriverInfo;
import com.flex.mobile.dao.model.DriverOrder;
import com.flex.mobile.dao.model.OrderInfo;
import com.flex.mobile.dao.model.UserStatus;
import com.flex.mobile.manager.DriverManager;
import com.flex.mobile.manager.FeedManager;
import com.flex.mobile.model.Address;
import com.flex.mobile.model.OrderMessage;
import com.flex.mobile.model.TaxiOrder;
import com.flex.mobile.model.User;
import com.flex.mobile.service.TaxiOrderService;
import com.flex.mobile.service.TimerService;
import com.flex.mobile.timer.WFTimerHandler;
import com.flex.mobile.timer.WFTimerKind;
import com.flex.mobile.util.CalenderUtil;
import com.flex.mobile.util.OrderNoGeneratorUtil;

public class TaxiOrderServiceImpl implements TaxiOrderService {

   private OrderInfoDao ordeInforDao;
   private FeedManager feedManager;
   private DriverInfoDao driverInfoDao;
   private CustInfoDao custInfoDao;
   private DriverOrderDao driverOrderDao;
   private DriverManager driverManager;
   private TimerService timerService;

   public void setTimerService(TimerService timerService) {
      this.timerService = timerService;
   }

   public void setDriverManager(DriverManager driverManager) {
      this.driverManager = driverManager;
   }

   public void setDriverOrderDao(DriverOrderDao driverOrderDao) {
      this.driverOrderDao = driverOrderDao;
   }

   public void setOrderDao(OrderInfoDao value) {
      this.ordeInforDao = value;
   }

   public void setFeedManager(FeedManager value) {
      this.feedManager = value;
   }

   public void setDriverDao(DriverInfoDao value) {
      this.driverInfoDao = value;
   }

   public void setCustInfoDao(CustInfoDao value) {
      this.custInfoDao = value;
   }

   public void init() {
      timerService.registeTimerHandler(new WFTimerHandler());
      timerService.startTimer();
   }

   /*
    * 0:普通叫车 1：机场叫车 2：加价叫车 用户提交订单时调用的API 1. 创建订单，生成订单号，订单状态 2. 选择合适的司机 3. 推送到司机端
    */
   @Override
   public TaxiOrder createTaxiOrder(TaxiOrder order) {
      OrderInfo orderInfo = new OrderInfo();
      orderInfo.setOrderNo(OrderNoGeneratorUtil.process());
      orderInfo.setCreateDate(new Date());
      orderInfo.setTargetAddress(order.getStartAddress().getDescription());
      orderInfo.setDestination(order.getEndAddress().getDescription());
      if (order.getStartTime() == null) {
         orderInfo.setTargetTime(new Date());
      } else {
         orderInfo.setTargetTime(order.getStartTime());
      }
      orderInfo.setOwnerId(order.getUser().getId());
      orderInfo.setOrderStatus(OrderInfoStatusConst.WAITING_ACCEPTED);

      orderInfo.setAirport(order.getAirPortCode());
      orderInfo.setFlightNumber(order.getAirNum());
      orderInfo.setOrderType(order.getOrderType());

      orderInfo = ordeInforDao.create(orderInfo);
      order.setId(orderInfo.getId());
      order.setOrderNo(orderInfo.getOrderNo());
      order.setStatus(OrderInfoStatusConst.WAITING_ACCEPTED);
      order.setCreateDate(orderInfo.getCreateDate());
      // 找司机
      List<DriverInfo> drivers = driverManager.findDriverInBuffer(order);
      OrderMessage message = new OrderMessage();
      if (order.getType() == OrderInfoTypeConst.COMMON_CALLTAXI) {
         message.setType(OrderMessage.MESSAGE_TYPE_REALTIME);
      } else {
         message.setType(OrderMessage.MESSAGE_TYPE_RESERVE);
      }
      List<DriverOrder> driverOrderList = new ArrayList<DriverOrder>();
      DriverOrder driverOrder;
      for (DriverInfo driver : drivers) {
         if (driver.getUserStatus().getCurrentStatus() == UserStatus.CURRENT_STATUS_ONLINE) {
            feedManager.sendTaxiOrderMsg(message, driver.getTelephone());
            driverOrder = new DriverOrder();
            driverOrder.setDriverId(driver.getId());
            driverOrder.setOrderId(orderInfo.getId());
            driverOrderList.add(driverOrder);
         }
      }
      // 插入临时表
      for (DriverOrder model : driverOrderList) {
         driverOrderDao.createTemp(model);
      }

      timerService.registeTimer(WFTimerKind.ORDER_PRETIME, orderInfo.getId()
            + "", "", "", CalenderUtil.addMinute(new Date(), 10).getTime());
      return order;
   }

   /*
    * 司机接受用户订单时调用的API 1. 修改订单状态（填入司机ID） 2. 推送给用户 3. 选出司机，通知司机，刷新相应的列表
    */
   @Override
   public long applyTaxiOrder(List<Number> orderIds, long driverId) {
      // 默认每次司机只能提交一个订单,抢单子规则，顺序开始抢，抢到哪一个就退出返回
      long result = 0l;
      OrderInfo orderInfo = null;
      TaxiOrder order = null;
      boolean flag = false;
      for (Number number : orderIds) {
         orderInfo = ordeInforDao.findById(number.longValue());
         if (orderInfo.getOrderStatus() == OrderInfoStatusConst.WAITING_ACCEPTED) {
            orderInfo.setOrderStatus(OrderInfoStatusConst.ACCEPTED);
            orderInfo.setDriverId(driverId);
            result = orderInfo.getId();
            // 数据库修改订单状态
            if (ordeInforDao.update(orderInfo)) {
               order = converOrderInfoToTaxiOrder(orderInfo);
               timerService.unregisteTimer(WFTimerKind.ORDER_PRETIME,
                     orderInfo.getId() + "");
               flag = true;
               break;
            }
         }
      }
      // 当flag为true时说明抢到一张单子，
      if (flag) {
         // 插入driverorder表中
         // DriverOrder driverOrder = new DriverOrder();
         // driverOrder.setDriverId(driverId);
         // driverOrder.setOrderId(orderInfo.getId());
         // driverOrderDao.create(driverOrder);
         // // 找出临时表中以前发过的司机，然后通知其他司机
         // List<DriverInfo> driverList = new ArrayList<DriverInfo>();
         // driverList.add(driverInfoDao.findById(driverId));
         // List<DriverOrder> driverOrderList =
         // driverOrderDao.findTempByOrderId(orderInfo.getId());
         // for (DriverOrder model : driverOrderList) {
         // driverList.add(driverInfoDao.findById(model.getDriverId()));
         // }
         // 发消息通知司机
         OrderMessage message = new OrderMessage();
         // message.setType(OrderMessage.MESSAGE_TYPE_REALTIME);
         // for (DriverInfo driver : driverList) {
         // feedManager.sendTaxiOrderMsg(message, driver.getTelephone());
         // }
         CustInfo userInfo = custInfoDao.findById(orderInfo.getOwnerId());
         message.setType(OrderMessage.MESSAGE_TYPE_APPLY_REALTIME);
         message.setBody(order);
         feedManager.sendTaxiOrderMsg(message, userInfo.getCellPhone1());
         File keystore = new File(this.getClass().getResource("/").getPath()
               + "javapns.p12");
         try {
            Push.alert("订单(" + order.getOrderNo() + ")被接受", keystore,
                  "12345678", false, userInfo.getIphoneToken());
         } catch (CommunicationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
         } catch (KeystoreException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
         } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
         }
      }
      return result;
   }

   /*
    * 暂时没用
    */
   @Override
   public TaxiOrder confirmTaxiOrder(TaxiOrder order) {
      OrderInfo orderInfo = new OrderInfo();
      orderInfo.setDestination(order.getStartAddress().getDescription());
      orderInfo.setTargetAddress(order.getEndAddress().getDescription());
      orderInfo.setTargetTime(order.getStartTime());
      orderInfo.setOwnerId(order.getUser().getId());
      orderInfo.setDriverId(order.getDriver().getId());
      orderInfo.setOrderStatus(order.getStatus());
      ordeInforDao.update(orderInfo);

      // DriverInfo driver = driverDao.findById(order.getDriver().getId());
      // feedManager.sendTaxiOrderMsg(order, driver.getTelephone());

      return order;
   }

   @Override
   public List<TaxiOrder> findRealTimeTaxiOrdersByDriver(long driverId) {
      // 去临时关系表，查有给司机发过哪些订单
      List<DriverOrder> driverOrderList = driverOrderDao
            .findTempByDriverId(driverId);
      if (driverOrderList == null || driverOrderList.size() == 0) {
         return new ArrayList<TaxiOrder>();
      }
      List<Long> orderIdsList = new ArrayList<Long>();
      for (DriverOrder driverOrder : driverOrderList) {
         orderIdsList.add(driverOrder.getOrderId());
      }
      List<OrderInfo> orderList = ordeInforDao.findByOrderIds(orderIdsList,
            OrderInfoTypeConst.COMMON_CALLTAXI,
            OrderInfoStatusConst.WAITING_ACCEPTED);
      List<OrderInfo> subOrder;
      if (orderList.size() > 5) {
         // 截取前面5条记录
         subOrder = orderList.subList(0, 5);
         return converOrderInfoListToTaxiOrder(subOrder);
      } else {
         return converOrderInfoListToTaxiOrder(orderList);
      }
   }

   @Override
   public List<TaxiOrder> findReserveTaxiOrdersByDriver(long driverId) {
      // 查询等到手里的预约订单
      List<OrderInfo> orderList = ordeInforDao
            .findWaitingOrderByType(OrderInfoTypeConst.RESERVED_CALLTAXI);
      List<OrderInfo> subOrder;
      if (orderList.size() > 5) {
         // 截取前面5条记录
         subOrder = orderList.subList(0, 5);
         return converOrderInfoListToTaxiOrder(subOrder);
      } else {
         return converOrderInfoListToTaxiOrder(orderList);
      }
   }

   @Override
   public List<TaxiOrder> findActiveTaxiOrdersByDriver(long driverId) {
      List<OrderInfo> orderList = ordeInforDao
            .findActivesByDriverId(driverId);
      List<OrderInfo> result = new ArrayList<OrderInfo>();
      OrderInfo current = null;
      Date nowDate = new Date();
      for (Iterator<OrderInfo> iterator = orderList.iterator(); iterator.hasNext();) {
         OrderInfo orderInfo = iterator.next();
         if (orderInfo.getTargetTime().before(nowDate)) {
            current = orderInfo;
            if (result.size() == 0) {
               result.add(0, current);
            }
            else {
               result.set(0, current);
            }
         }
         else {
            result.add(orderInfo);
         }
      }
      
      List<OrderInfo> subOrder;
      if (result.size() > 5) {
         // 截取前面5条记录
         subOrder = result.subList(0, 5);
         return converOrderInfoListToTaxiOrder(subOrder);
      } else {
         return converOrderInfoListToTaxiOrder(result);
      }
   }

   @Override
   public List<TaxiOrder> findTaxiOrdersByDriverId(long driverId) {
      List<OrderInfo> orderInfoList = ordeInforDao.findByDriverId(driverId);
      return converOrderInfoListToTaxiOrder(orderInfoList);
   }

   @Override
   public TaxiOrder getTaxiOrderDetail(long orderId) {
      return converOrderInfoToTaxiOrder(ordeInforDao.findById(orderId));
   }

   @Override
   public List<TaxiOrder> findTaxiOrdersByUserId(long userId) {
      return converOrderInfoListToTaxiOrder(ordeInforDao.findByUserId(userId));
   }

   @Override
   public boolean cancelTaxiOrder(TaxiOrder order) {
      // 撤销单子，修改订单状态，然后通知已经成功处理此单子的司机
      OrderInfo orderInfo = ordeInforDao.findById(order.getId());
      // 当此单子受理成功时，才找司机，否则，不用通知仅更改状态
      if (orderInfo.getOrderStatus() == OrderInfoStatusConst.ACCEPTED) {
         DriverInfo driver = driverInfoDao.findById(orderInfo.getDriverId());
         OrderMessage message = new OrderMessage();
         if (orderInfo.getOrderType() == OrderInfoTypeConst.COMMON_CALLTAXI) {
            message.setType(OrderMessage.MESSAGE_TYPE_REALTIME);
         } else {
            message.setType(OrderMessage.MESSAGE_TYPE_RESERVE);
         }
         feedManager.sendTaxiOrderMsg(message, driver.getTelephone());
      }
      orderInfo.setOrderStatus(OrderInfoStatusConst.REVOCATION);
      return ordeInforDao.update(orderInfo);
   }

   private List<TaxiOrder> converOrderInfoListToTaxiOrder(
         List<OrderInfo> orderList) {
      List<TaxiOrder> taxiOrderList = new ArrayList<TaxiOrder>();
      for (OrderInfo orderInfo : orderList) {
         taxiOrderList.add(converOrderInfoToTaxiOrder(orderInfo));
      }
      return taxiOrderList;
   }

   private TaxiOrder converOrderInfoToTaxiOrder(OrderInfo orderInfo) {
      if (null == orderInfo) {
         return null;
      }
      TaxiOrder taxiOrder = new TaxiOrder();
      taxiOrder.setId(orderInfo.getId());
      taxiOrder.setOrderNo(orderInfo.getOrderNo());
      Address startAddress = new Address();
      startAddress.setDescription(orderInfo.getTargetAddress());
      taxiOrder.setStartAddress(startAddress);
      Address targetAddress = new Address();
      targetAddress.setDescription(orderInfo.getDestination());
      taxiOrder.setEndAddress(targetAddress);
      taxiOrder.setStartTime(orderInfo.getTargetTime());
      taxiOrder.setType(orderInfo.getOrderType());
      taxiOrder.setStatus(orderInfo.getOrderStatus());

      taxiOrder.setStartTime(orderInfo.getTargetTime());
      taxiOrder.setDescription(orderInfo.getDestination());
      taxiOrder.setAirNum(orderInfo.getFlightNumber());
      taxiOrder.setAirDate(orderInfo.getTargetTime());
      taxiOrder.setStationCode(orderInfo.getAirport());
      taxiOrder.setTrainNum(orderInfo.getFlightNumber());
      taxiOrder.setTrainDate(orderInfo.getTargetTime());
      taxiOrder.setCreateDate(orderInfo.getCreateDate());

      CustInfo custInfo = custInfoDao.findById(orderInfo.getOwnerId());
      if (null != custInfo) {
         User user = new User();
         user.setId(custInfo.getId());
         user.setPassword(custInfo.getPassword());
         user.setPhone(custInfo.getCellPhone1());
         user.setType(User.USER_TYPE_CUST);
         user.setUserName(custInfo.getUserName());
         taxiOrder.setUser(user);
      }

      DriverInfo driver = null;
      if (orderInfo.getDriverId() > 0) {
         driver = driverInfoDao.findById(orderInfo.getDriverId());
      }
      if (null != driver) {
         User driverUser = new User();
         driverUser.setId(driver.getId());
         driverUser.setPassword(driver.getPassword());
         driverUser.setPhone(driver.getTelephone());
         driverUser.setType(User.USER_TYPE_DRIVER);
         driverUser.setUserName(driver.getUserName());
         taxiOrder.setDriver(driverUser);
      }
      return taxiOrder;
   }

   // test
   public static void main(String[] args) throws Exception {
      File keystore = new File(TaxiOrderServiceImpl.class.getResource("/")
            .getPath() + "javapns.p12");
      System.out.println(keystore.getName().toString());
      List<PushedNotification> notifications = Push.alert("订单被接受", keystore,
            "12345678", false,
            "a74438dc455e3e82a941d848f05c238b3bdfd5bc126f071ca03b975d0d9fd0e0");
      for (PushedNotification notification : notifications) {
         String token = notification.getDevice().getToken();
         if (notification.isSuccessful()) {
            /* Apple accepted the notification and should deliver it */
            System.out.println("Push notification sent successfully to: "
                  + token);
            /* Still need to query the Feedback Service regularly */
         } else {
            /* Add code here to remove invalidToken from your database */

            /* Find out more about what the problem was */
            Exception theProblem = notification.getException();
            theProblem.printStackTrace();

            /*
             * If the problem was an error-response packet returned by Apple,
             * get it
             */
            ResponsePacket theErrorResponse = notification.getResponse();
            if (theErrorResponse != null) {
               System.out.println(theErrorResponse.getMessage());
            }
         }
      }

   }

}
